#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <WiFiManager.h>

// topicString与前端代码中发送topic一致 需要修改
String topicString = "connect_all_esp01";
//配网的WiFi名称
const char* wifIName = "esp01_test";
// mqtt服务器地址，这个是免费公用的服务器
const char* mqttServer = "116.198.232.194";

WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);

int GPIO = 0;

void setup() {
   // 设置串口
   Serial.begin(115200);
   // 设置内置LED引脚为输出模式
   pinMode(GPIO, OUTPUT);
  
   // 连接WiFi
   connectWifi();

   // 设置MQTT服务器和端口号
   mqttClient.setServer(mqttServer, 1883);
   mqttClient.setCallback(receiveCallback);

   // 连接MQTT服务器
   connectMQTTServer();
}

void loop() {
  // 开发板成功连接服务器    
  if (mqttClient.connected()) {
    // 保持客户端心跳
    mqttClient.loop();          
  } else {
    // 尝试连接服务器                  
    connectMQTTServer();    
  }
}

void connectMQTTServer(){
  // 避免与其它ESP8266设备重名 需要修改-----------
  String clientId = "ESP01-人在传感-测试-" + WiFi.macAddress();

  // 连接MQTT服务器
  if (mqttClient.connect(clientId.c_str())) { 
    Serial.println("MQTT Connected.");
    // 订阅指定主题
    subscribeTopic(); 
  } else {
    Serial.print("MQTT Server Connect Failed. Client State:");
    Serial.println(mqttClient.state());
    delay(3000);
  }   
}

// 收到信息
void receiveCallback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message Received [");
  Serial.print(topic);
  Serial.print("] ");
  
  if ((char)payload[0] == '1') {     // 如果收到的信息以“1”为开始
    digitalWrite(GPIO, HIGH);  // 则点亮LED。
    Serial.println("LED ON");
  } else {                           
    digitalWrite(GPIO, LOW); // 否则熄灭LED。
    Serial.println("LED OFF");
  }
}

// 订阅指定主题
void subscribeTopic(){
  char subTopic[topicString.length() + 1];  
  strcpy(subTopic, topicString.c_str());
  
  // 通过串口监视器输出是否成功订阅主题以及订阅的主题名称
  if(mqttClient.subscribe(subTopic)){
    Serial.println("Subscrib Topic:");
    Serial.println(subTopic);
  } else {
    Serial.print("Subscribe Fail...");
  }  
}

// 连接wifi
void connectWifi(){

  WiFiManager wifiManager;

  wifiManager.autoConnect(wifIName);
  Serial.println("WiFi Connected!");  
  Serial.println(""); 
}
